//---------------------------------------------------------------------------

#include <vcl.h>
#include <tchar.h>

#pragma hdrstop

#include "fShadowFBOC.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "GLS.BaseClasses"
#pragma link "GLS.Cadencer"
#pragma link "GLS.Coordinates"

#pragma link "GLSL.CustomShader"
#pragma link "GLS.FBORenderer"
#pragma link "GLS.GeomObjects"
#pragma link "GLS.HUDObjects"
#pragma link "GLS.Material"
#pragma link "GLS.Objects"
#pragma link "GLS.Scene"
#pragma link "Formats.DDSImage"
#pragma link "GLS.SimpleNavigation"
#pragma link "GLS.VectorFileObjects"
#pragma link "GLS.SceneViewer"
#pragma link "GLS.FileMD2"
#pragma link "GLSL.Shader"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}

//---------------------------------------------------------------------------
void __fastcall TForm1::PrepareShadowMappingRender(TObject *Sender, TGLRenderContextInfo &rci)

{

  // prepare shadow mapping matrix
  FInvCameraMatrix = rci.PipelineTransformation->InvModelViewMatrix;
  // go from eye space to light's "eye" space
  *FEyeToLightMatrix = MatrixMultiply(*FInvCameraMatrix, *FLightModelViewMatrix);
  // then to clip space
  *FEyeToLightMatrix = MatrixMultiply(*FEyeToLightMatrix, *FLightProjMatrix);
  // and finally make the [-1..1] coordinates into [0..1]
  *FEyeToLightMatrix = MatrixMultiply(*FEyeToLightMatrix, *FBiasMatrix);
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  TFileName Path = GetCurrentAssetPath();
  // Loading textures
  SetCurrentDir(Path  + "\\texture");
  GLMaterialLibrary1->TextureByName("Chekers")->Image->LoadFromFile("marbletiles.jpg");
  GLMaterialLibrary1->TextureByName("Chekers")->Disabled = false;
  GLMaterialLibrary1->TextureByName("Chekers2")->Image->LoadFromFile("concrete.jpg");
  GLMaterialLibrary1->TextureByName("Chekers2")->Disabled = false;
  GLMaterialLibrary1->TextureByName("Lightspot")->Image->LoadFromFile("flare1.bmp");
  GLMaterialLibrary1->TextureByName("Lightspot")->Disabled = false;

  // Loading skeletal models with skin texture
  SetCurrentDir(Path  + "\\modelext");
  GLFreeForm1->LoadFromFile("waste.md2");
  GLFreeForm1->Scale->Scale(0.05);
  GLFreeForm1->Position->Y = GLPlane1->Position->Y + 0.6;
  FBiasMatrix =
	&CreateScaleAndTranslationMatrix(VectorMake(0.5, 0.5, 0.5), VectorMake(0.5, 0.5, 0.5));
  GLMaterialLibrary1->TextureByName("bark")->Image->LoadFromFile("waste.jpg");
  GLMaterialLibrary1->TextureByName("bark")->Disabled = false;

  // Loading cubemap
  SetCurrentDir(Path  + "\\cubemap");
  GLMaterialLibrary1->TextureByName("mask")->Image->LoadFromFile("masks.dds");
  GLMaterialLibrary1->TextureByName("mask")->Disabled = false;

  // Loading shaders
  SetCurrentDir(Path  + "\\shader");
  GLSLShader1->VertexProgram->LoadFromFile("shadowmap_vp.glsl");
  GLSLShader1->FragmentProgram->LoadFromFile("shadowmapvis_fp.glsl");
  GLSLShader1->Enabled = true;
  GLSLShader2->VertexProgram->LoadFromFile("shadowmap_vp.glsl");
  GLSLShader2->FragmentProgram->LoadFromFile("shadowmap_fp.glsl");
  GLSLShader2->Enabled = true;
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
  GLSceneViewer1->Camera->SceneScale = GLSceneViewer1->ClientWidth / 400;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::GLCadencer1Progress(TObject *Sender, const double deltaTime,
		  const double newTime)
{
  GLTorus1->Turn(deltaTime * 25);
  GLCylinder1->Turn(deltaTime * 50);
  GLCamera2->Position->Rotate(VectorMake(0, 1, 0), deltaTime * 0.1);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::GLSLShader1Apply(TGLCustomGLSLShader *Shader)
{
  Shader->Param["ShadowMap"]->AsTexture2D[0] =
	GLMaterialLibrary1->TextureByName(LightFBORenderer->DepthTextureName);
  // set compare to none so we can read off the depth value directly
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::GLSLShader1UnApply(TGLCustomGLSLShader *Shader, bool &ThereAreMorePasses)

{
  // reset the compare mode to default
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::GLSLShader2Apply(TGLCustomGLSLShader *Shader)
{
  Shader->Param["ShadowMap"]->AsTexture2D[1] =
	GLMaterialLibrary1->TextureByName(LightFBORenderer->DepthTextureName);
  Shader->Param["LightspotMap"]->AsTexture2D[2] =
	GLMaterialLibrary1->TextureByName("Lightspot");
  Shader->Param["Scale"]->AsFloat = 16.0;
  Shader->Param["Softly"]->AsInteger = 1;
  Shader->Param["EyeToLightMatrix"]->AsMatrix4f = *FEyeToLightMatrix;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::GLSLShader2Initialize(TGLCustomGLSLShader *Shader)
{
  Shader->Param["TextureMap"]->AsTexture2D[0] =
	GLMaterialLibrary1->TextureByName("Chekers2");
  Shader->Param["ShadowMap"]->AsTexture2D[1] =
	GLMaterialLibrary1->TextureByName(LightFBORenderer->DepthTextureName);
  Shader->Param["LightspotMap"]->AsTexture2D[2] =
	GLMaterialLibrary1->TextureByName("Lightspot");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::GLSceneViewer1BeforeRender(TObject *Sender)
{
  if ((GLSceneViewer1->Buffer->RenderingContext->GL->EXT_framebuffer_object) = false)
  {
	ShowMessage("Sorry, this demo requires GL_EXT_framebuffer_object and either");
	Close();
  }
}
//---------------------------------------------------------------------------
